import os
import re
from urllib.parse import urlparse, urljoin

import requests
import traceback
from lxml import etree

from bs4 import BeautifulSoup

# 爬取的链接
url = ""

# 域名
main_url = "https://www.ddkk.com"

# 附件存储的地址
file_img_path = '图片/'

folder = '/'

new_line = '\n'


def pull_away_html_note(url):
    '''
    获取网页源码 Xpath标签识别： //div[@id="article-list"]/ul/li/a
    :param url: 网页链接
    :return: 网页源码
    '''
    headers = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.105 Safari/537.36'
    }
    response = requests.get(url, headers=headers)
    response.encoding = 'utf-8'

    # 处理响应数据
    html_text = etree.HTML(response.text)

    # TODO 文件名称出现的特殊符号进行替换处理 避免文件名和文章内容不对应

    # 处理该片文章需要解析的方法
    analysis_method = urlparse(url).path.split("/")[1]
    if analysis_method == 'zhuanlan':
        zhuanlan(html_text)
    elif analysis_method == 'category':
        category(html_text)
    else:
        print(f"该地址不支持解析：{url}")


def zhuanlan(html_text):
    data_body = html_text.xpath("//nav[@id='toc']/ul/li", default=None, smart_strings=False)
    # 文件夹标号
    folder_num = 0

    # 文件标号
    file_num = 0

    # 文件临时存储地址
    folder_path = folder

    # 文件夹地址
    chapter_name = None
    for item in data_body:
        # 文件加名称（标题）
        file_name = item.xpath('button//text()')
        list_title_name = item.xpath('ul/li')
        if file_name:
            folder_num += 1
            file_num = 0
            chapter_name = f"{folder_path}{folder_num}、{file_name[0].strip()}"
            print(chapter_name)
        else:
            print('未解析能到文件夹名称')

        if chapter_name != None or len(list_title_name) > 0:
            # html 转换成字符串
            for li_item in list_title_name:
                html_content = etree.tostring(li_item, encoding='unicode')
                html_title_soup = BeautifulSoup(html_content, 'html.parser')
                for a_tag in html_title_soup.find_all('a'):
                    # 写入文件标题
                    file_num += 1
                    # 正则判断标题前缀
                    head_title_data = re.sub(r'^\d+(\.\d+)?、?', '', a_tag.get_text()).replace("/", " ")
                    md_file_path = f'{chapter_name}/{file_num}、{head_title_data}'
                    note_info_zhuanlan(f"{main_url}{a_tag.get('href')}", md_file_path)

            print("-" * 10, "目录分割", "-" * 10)
        else:
            print('未解析能到.md文件名称！')


def note_info_zhuanlan(note_url, file_path):
    # 处理 folder 地址图片初始化
    global folder
    folder = f"{file_path.rsplit('/', 1)[0]}/"

    try:
        # 访问下一层并把地址添加到 `file_path`
        headers = {
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.105 Safari/537.36'
        }
        response = requests.get(note_url, headers=headers)
        response.encoding = 'utf-8'

        # 处理响应数据
        html_text = etree.HTML(response.text)

        # 根据 xpath 组件选择器选择所需
        article_a_text = html_text.xpath("//article/ul/li//text()", default=None, smart_strings=False)
        article_a_href = html_text.xpath("//article/ul/li/a/@href", default=None, smart_strings=False)
        # 判断是否是可访问列表
        if article_a_text and article_a_href and len(article_a_text) == len(article_a_href):
            article_a_data = {key: val for key, val in zip(article_a_text, article_a_href)}
            for key, val in article_a_data.items():
                # 判断是否是无需列表还存在链接情况，递归连续处理
                if article_a_href:
                    note_info_zhuanlan(f"{main_url}{val}", f"{file_path}/{key}")
        else:
            # 文件路径特殊字符处理
            file_path = file_path_special_replace(file_path)
            # 创建.md 文件
            ul_li_file_name = f"{file_path}.md"
            # 判断文件是否存在
            if os.path.exists(ul_li_file_name):
                os.remove(ul_li_file_name)
            else:
                # 创建文件夹
                os.makedirs(os.path.dirname(ul_li_file_name), exist_ok=True)

            # 文件存储的目录
            file_storge_path = file_path.split("/")[-1]

            # 把文件标题和链接地址录入
            text_list_md = f"# [{file_storge_path}]({note_url})"
            with open(f"{ul_li_file_name}", 'w', encoding='utf-8') as f:
                f.write(f"{text_list_md}{new_line}")

            # 开始给文件中写入内容
            data_body = html_text.xpath('//article/node()', default=None, smart_strings=False)
            for item in data_body:
                # 判断是不是字符串
                if isinstance(item, str):
                    with open(ul_li_file_name, 'a', encoding='utf-8') as f:
                        f.write(html_label_markdown(item))
                else:
                    with open(ul_li_file_name, 'a', encoding='utf-8') as f:
                        f.write(html_label_markdown(item))

    except Exception as e:
        err_val = traceback.extract_tb(e.__traceback__)
        print(e, f'报错行数{err_val[-1].lineno}', '-' * 10, note_url)


def category(html_text):
    # 处理 folder 地址图片初始化
    global folder

    data_body = html_text.xpath('//div[@id="article-list"]/ul/li', default=None, smart_strings=False)
    # 文件夹标号
    folder_num = 0

    # 文件标号
    file_num = 0
    # 文件夹地址
    chapter_name = None

    # 文件临时存储地址
    folder_path = folder

    for item in data_body:
        # 文件夹名称
        file_name = item.xpath('a[@href="javascript:;"]//text()')
        if file_name:
            folder_num += 1
            file_num = 0
            chapter_name = f"{folder_path}{folder_num}、{file_name[0].strip()}/"

        elif chapter_name != None or len(item.xpath('a//text()')) > 0:
            # 处理 图片 存储地址
            if chapter_name != None:
                folder = f"{chapter_name}/"

            # 通过没有标题类型的来创建文件夹
            if chapter_name == None:
                chapter_name = f"{folder}"

            # html 转换成字符串
            html_content = etree.tostring(item, encoding='unicode')
            html_title_soup = BeautifulSoup(html_content, 'html.parser')
            for a_tag in html_title_soup.find_all('a'):
                # 写入文件标题
                file_num += 1
                # 正则判断标题前缀
                head_title_data = re.sub(r'^\d+(\.\d+)?、?', '', a_tag.get_text())
                a_tag.replace_with(f'# 标题：[{head_title_data}]({main_url}{a_tag.get("href")})')
                head_title_data = head_title_data.replace("/", " ")
                file_path_md = file_path_special_replace(f'{chapter_name}{file_num}、{head_title_data}.md')

                # 判断文件是否存在
                if os.path.exists(file_path_md):
                    os.remove(file_path_md)
                else:
                    # 创建文件夹
                    os.makedirs(os.path.dirname(file_path_md), exist_ok=True)

                with open(file_path_md, 'w', encoding='utf-8') as f:
                    f.write(f'{html_title_soup.get_text()}{new_line}')
                note_info_category(f'{main_url}{a_tag.get("href")}', file_path_md)

        else:
            print('解析文件数据异常！')


def note_info_category(note_url, file_path):
    '''
    获取网页源码 Xpath标签识别： //div[@id="article-list"]/ul/li/a
    :param url: 网页链接
    :return: 网页源码
    '''

    #     解析笔记内容
    headers = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.105 Safari/537.36'
    }
    response = requests.get(note_url, headers=headers)
    response.encoding = 'utf-8'

    # 处理响应数据
    html_text = etree.HTML(response.text)

    data_body = html_text.xpath('//article/node()', default=None, smart_strings=False)

    # TODO 文件使用
    os.makedirs(os.path.dirname(file_path), exist_ok=True)

    # 提取笔记内容
    try:
        for item in data_body:
            # 判断是不是字符串
            if isinstance(item, str):
                with open(file_path, 'a', encoding='utf-8') as f:
                    f.write(html_label_markdown(item))
            else:
                with open(file_path, 'a', encoding='utf-8') as f:
                    f.write(html_label_markdown(item))
                # print(html_label_markdown(item))
    except Exception as e:
        err_val = traceback.extract_tb(e.__traceback__)
        print(e, f'报错行数{err_val[-1].lineno}', '-' * 10, note_url)


def html_label_markdown(html_object):
    '''
    递归处理传入的标签对象
    :param html_text:
    :return:
    '''
    markdown_content = ""
    # 判断当前标签是对象还是文本
    if isinstance(html_object, etree._Element):
        # html 转换成字符串
        html_content = etree.tostring(html_object, encoding='unicode')
        # 使用 soup = BeautifulSoup(html_content, 'html.parser'', markup_name='html')
        # 解析 HTML 文档
        soup = BeautifulSoup(html_content, 'html.parser')

        # 替换 <h1> 和 </h1> 为 Markdown 标题
        for h1_tag in soup.find_all('h1'):
            h1_text = h1_tag.get_text()
            if h1_tag.find("a"):
                for h1_a_tag in h1_tag.find_all('a'):
                    h1_text = f"# [{h1_text}{h1_a_tag.get_text()}]({h1_a_tag.get('href')})"
            else:
                h1_text = f"# {h1_text}"
            h1_tag.replace_with(f'{h1_text}')

        # 替换 <h2> 和 </h2> 为 Markdown 标题
        for h2_tag in soup.find_all('h2'):
            h2_text = h2_tag.get_text()
            if h2_tag.find("a"):
                for h2_a_tag in h2_tag.find_all('a'):
                    h2_text = f"## [{h2_text}{h2_a_tag.get_text()}]({h2_a_tag.get('href')})"
            else:
                h2_text = f"## {h2_text}"
            h2_tag.replace_with(f'{h2_text}')

        # 替换 <h3> 和 </h3> 为 Markdown 标题
        for h3_tag in soup.find_all('h3'):
            h3_text = h3_tag.get_text()
            if h3_tag.find("a"):
                for h3_a_tag in h3_tag.find_all('a'):
                    h3_text = f"# [{h3_text}{h3_a_tag.get_text()}]({h3_a_tag.get('href')})"
            else:
                h3_text = f"### {h3_text}"
            h3_tag.replace_with(f'{h3_text}')

        # 替换 <h4> 和 </h4> 为 Markdown 标题
        for h4_tag in soup.find_all('h4'):
            h4_text = h4_tag.get_text()
            if h4_tag.find("a"):
                for h4_a_tag in h4_tag.find_all('a'):
                    h4_text = f"# [{h4_text}{h4_a_tag.get_text()}]({h4_a_tag.get('href')})"
            else:
                h4_text = f"#### {h4_text}"

            h4_tag.replace_with(f'{h4_text}')

        # 替换 <h5> 和 </h5> 为 Markdown 标题
        for h5_tag in soup.find_all('h5'):
            h5_text = h5_tag.get_text()
            if h5_tag.find("a"):
                for h5_a_tag in h5_tag.find_all('a'):
                    h5_text = f"##### [{h5_text}{h5_a_tag.get_text()}]({h5_a_tag.get('href')})"
            else:
                h5_text = f"##### {h5_text}"

            h5_tag.replace_with(f'{h5_text}')

        # 替换 <h6> 和 </h6> 为 Markdown 标题
        for h6_tag in soup.find_all('h6'):
            h6_text = h6_tag.get_text()
            if h6_tag.find("a"):
                for h6_a_tag in h6_tag.find_all('a'):
                    h6_text = f"# [{h6_text}{h6_a_tag.get_text()}]({h6_a_tag.get('href')})"
            else:
                h6_text = f"###### {h6_text}"

            h6_tag.replace_with(f'{h6_text}')

        # 替换 <strong> 和 </strong> 为 Markdown 加粗语法
        for a_tag in soup.find_all('a'):
            a_text_val = a_tag.get_text()
            href = a_tag.get('href')
            if href:
                a_text_val = f'[{a_text_val}]({href})'
            a_tag.replace_with(f'{a_text_val}')

        # 替换 <strong> 和 </strong> 为 Markdown 加粗语法
        for strong_tag in soup.find_all('strong'):
            strong_tag.replace_with(f'**{strong_tag.get_text()}**')

        # 替换 <em> 和 </em> 为 Markdown 斜体语法
        for em_tag in soup.find_all('em'):
            em_tag.replace_with(f'*{em_tag.get_text()}*')

        # 替换 <pre> 和 </pre> 为 Markdown 代码段落
        for pre_tag in soup.find_all('pre'):
            pre_tag.replace_with('```\n' + f'{pre_tag.get_text().strip()}' + '\n```')

        # 替换 <code> 和 </code> 为 Markdown 代码关键字
        for code_tag in soup.find_all('code'):
            code_tag.replace_with('`' + f'{code_tag.get_text()}' + '`')

        # 替换 <blockquote> 和 </blockquote> 为 Markdown 注释
        for blockquote_tag in soup.find_all('blockquote'):
            blockquote_list_str = blockquote_tag.get_text().strip().split('\n')
            # 处理<blockquote> 转换> 不会换行的问题
            blockquote_text = ''.join(
                f'&gt; {blockquote_str}\n'f'{"&gt; " + new_line if index < len(blockquote_list_str) - 1 else ""}'
                for index, blockquote_str in enumerate(blockquote_list_str)
            )
            blockquote_tag.replace_with(blockquote_text)

        # 替换 <img> 和 </img> 为 Markdown 图片
        for img_tag in soup.find_all('img'):
            img_src = f'{main_url}{img_tag.get("src")}'
            img_file = download_file(img_src, folder)
            img_tag.replace_with('\n' + f'![{img_tag.get("alt")}]({img_file})' + '\n')

        # 替换 <table> 和 </table> 为 Markdown 表格   table_tag.findAll("thead")[0].findAll("th")[0].next
        for table_tag in soup.find_all('table'):
            # 读取 thead 标签 表单
            headers = list()
            rows = []
            if table_tag.find("thead"):
                headers = [th.get_text() for th in table_tag.find("thead").find_all("th")]

            if table_tag.find("tbody"):
                for tr in table_tag.find("tbody").find_all("tr"):
                    if len(headers) > 0:
                        row = [th.get_text() for th in tr.find_all("td")]
                        row_all_none = True if len(row) else False
                        if row_all_none:
                            rows.append(row)
                    else:
                        headers = [td.get_text() for td in tr.find_all("th")]

            markdown_table = '| ' + ' | '.join(headers) + ' |\n'
            markdown_table += '| ' + ' | '.join([':---'] * len(headers)) + ' |\n'
            for row in rows:
                markdown_table += '| ' + ' | '.join(row) + ' |\n'

            table_tag.replace_with(f'{markdown_table}')

        # 替换 <p> 和 </p> 为 Markdown 段落；p标签放在最后
        for p_tag in soup.find_all('p'):
            p_tag.replace_with(p_tag.get_text().strip())

        # 获取最终的 Markdown 内容
        markdown_content = soup.prettify()
        if markdown_content.find('&amp;gt;') > -1:
            markdown_content = markdown_content.replace('&amp;gt;', '>')

        if markdown_content.find('&lt;') > -1:
            markdown_content = markdown_content.replace('&lt;', '<')

        if markdown_content.find('&gt;') > -1:
            markdown_content = markdown_content.replace('&gt;', '>')

    elif isinstance(html_object, str):
        markdown_content = f"{html_object}"
    else:
        markdown_content = f"🐷🐷🐷{html_object}"
    return markdown_content


def download_file(file_img_url, file_path):
    """
    下载文件
    :param file_img_url: 文件路径
    :param file_path: 文件保存路径
    :return:
    """
    headers = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.105 Safari/537.36'
    }
    file_path = f'{file_path}{file_img_path}'
    try:
        # 发送GET请求
        response = requests.get(file_img_url, headers=headers, stream=True)
        response.encoding = 'utf-8'

        response.raise_for_status()  # 检查请求是否成功

        # 确定文件名
        parsed_url = urlparse(file_img_url)
        file_name = parsed_url.path.split('/')[-1]
        if not file_name:
            file_name = "downloaded_file"

        # 构建完整的保存路径
        full_save_path = urljoin(file_path, file_name)

        # 确保保存路径的目录存在
        os.makedirs(os.path.dirname(full_save_path), exist_ok=True)

        # 保存文件
        with open(full_save_path, 'wb') as file:
            for chunk in response.iter_content(chunk_size=8192):
                file.write(chunk)

        print(f"文件已下载并保存到: {full_save_path}")
        return f'{file_img_path}{file_name}'

    except requests.exceptions.RequestException as e:
        print(f"请求错误: {e}")
    except Exception as e:
        print(f"发生错误: {e}")


def file_path_special_replace(file_path):
    """文件路径特殊字符替换"""
    if file_path.find('//') > -1:
        file_path = file_path.replace('//', '')

    if file_path.find('\\') > -1:
        file_path = file_path.replace('\\', '')

    if file_path.find('"') > -1:
        file_path = file_path.replace('"', '`')

    if file_path.find("'") > -1:
        file_path = file_path.replace("'", "`")

    if file_path.find('?') > -1:
        file_path = file_path.replace('?', '？')

    if file_path.find('*') > -1:
        file_path = file_path.replace('*', '＊')

    if file_path.find(':') > -1:
        file_path = file_path.replace(':', '：')

    if file_path.find('||') > -1:
        file_path = file_path.replace('||', 'or')

    if file_path.find('|') > -1:
        file_path = file_path.replace('|', 'or')

    if file_path.find('>') > -1:
        file_path = file_path.replace('>', '&gt;')

    if file_path.find('<') > -1:
        file_path = file_path.replace('<', '&lt;')
    return file_path


if __name__ == '__main__':
    study_data_url = list()
    # Java 面试题笔记
    # study_data_url.append({'file_path': 'JAVA/JAVA面试题7500题/', 'url': 'https://www.ddkk.com/category/newtiku/index.html'})

    # Java 并发
    # study_data_url.append({'file_path': 'JAVA/JAVA并发/Java并发入门/', 'url': 'https://www.ddkk.com/category/java/concurrency/1/index.html'})
    # study_data_url.append({'file_path': 'JAVA/JAVA并发/Java并发基础/', 'url': 'https://www.ddkk.com/category/java/concurrency/4/index.html'})
    # study_data_url.append({'file_path': 'JAVA/JAVA并发/Java多线程/', 'url': 'https://www.ddkk.com/category/java/concurrency/2/index.html'})
    # study_data_url.append({'file_path': 'JAVA/JAVA并发/Java集合框架/','url': 'https://www.ddkk.com/category/java/concurrency/3/index.html'})
    # study_data_url.append({'file_path': 'JAVA/JAVA并发/Java并发实战(1)/','url': 'https://www.ddkk.com/category/java/concurrency/5/index.html'})
    # study_data_url.append({'file_path': 'JAVA/JAVA并发/Java并发实战(2)/','url': 'https://www.ddkk.com/category/java/concurrency/6/index.html'})
    # study_data_url.append({'file_path': 'JAVA/JAVA并发/Java并发实战(3)/','url': 'https://www.ddkk.com/category/java/concurrency/7/index.html'})
    # study_data_url.append({'file_path': 'JAVA/JAVA并发/Java并发实战(4)/','url': 'https://www.ddkk.com/category/java/concurrency/8/index.html'})
    # study_data_url.append({'file_path': 'JAVA/JAVA并发/Java_JUC源码分析(1)/', 'url': 'https://www.ddkk.com/category/java/concurrency/9/index.html'})
    # study_data_url.append({'file_path': 'JAVA/JAVA并发/Java_JUC源码分析(2)/', 'url': 'https://www.ddkk.com/category/java/concurrency/10/index.html'})
    # study_data_url.append({'file_path': 'JAVA/JAVA并发/Java_JUC源码分析(3)/', 'url': 'https://www.ddkk.com/category/java/concurrency/11/index.html'})
    # study_data_url.append({'file_path': 'JAVA/JAVA并发/Java_JUC源码分析(4)/', 'url': 'https://www.ddkk.com/category/java/concurrency/12/index.html'})

    # JVM实战
    # study_data_url.append({'file_path': 'JAVA/JVM/JVM实战(1)/', 'url': 'https://www.ddkk.com/category/java/jvm/1/index.html'})
    # study_data_url.append({'file_path': 'JAVA/JVM/JVM实战(2)/', 'url': 'https://www.ddkk.com/category/java/jvm/2/index.html'})
    # study_data_url.append({'file_path': 'JAVA/JVM/JVM实战(3)/', 'url': 'https://www.ddkk.com/category/java/jvm/3/index.html'})
    # study_data_url.append({'file_path': 'JAVA/JVM/JVM实战(4)/', 'url': 'https://www.ddkk.com/category/java/jvm/4/index.html'})
    # study_data_url.append({'file_path': 'JAVA/JVM/JVM实战(5)/', 'url': 'https://www.ddkk.com/category/java/jvm/5/index.html'})
    # study_data_url.append({'file_path': 'JAVA/JVM/JVM实战(6)/', 'url': 'https://www.ddkk.com/category/java/jvm/6/index.html'})
    # study_data_url.append({'file_path': 'JAVA/JVM/JVM实战(7)/', 'url': 'https://www.ddkk.com/category/java/jvm/7/index.html'})
    # study_data_url.append({'file_path': 'JAVA/JVM/JVM实战(8)/', 'url': 'https://www.ddkk.com/category/java/jvm/11/index.html'})
    # study_data_url.append({'file_path': 'JAVA/JVM/JVM调优实战(1)/', 'url': 'https://www.ddkk.com/category/java/jvm/8/index.html'})
    # study_data_url.append({'file_path': 'JAVA/JVM/JVM调优实战(2)/', 'url': 'https://www.ddkk.com/category/java/jvm/9/index.html'})
    # study_data_url.append({'file_path': 'JAVA/JVM/JVM调优实战(3)/', 'url': 'https://www.ddkk.com/category/java/jvm/10/index.html'})
    # study_data_url.append({'file_path': 'JAVA/JVM/JVM调优实战(4)/', 'url': 'https://www.ddkk.com/category/java/jvm/12/index.html'})

    # ORM 框架
    # study_data_url.append({'file_path': 'JAVA/ORM框架/MyBatis教程/', 'url': 'https://www.ddkk.com/category/orm/mybatis/1/index.html'})
    # study_data_url.append({'file_path': 'JAVA/ORM框架/MyBatis速成/', 'url': 'https://www.ddkk.com/category/orm/mybatis/9/index.html'})
    # study_data_url.append({'file_path': 'JAVA/ORM框架/MyBatis实战（1）/', 'url': 'https://www.ddkk.com/category/orm/mybatis/6/index.html'})
    # study_data_url.append({'file_path': 'JAVA/ORM框架/MyBatis源码解析（1）/', 'url': 'https://www.ddkk.com/category/orm/mybatis/5/index.html'})
    # study_data_url.append({'file_path': 'JAVA/ORM框架/MyBatis源码解析（2）/', 'url': 'https://www.ddkk.com/category/orm/mybatis/7/index.html'})
    # study_data_url.append({'file_path': 'JAVA/ORM框架/MyBatis-Plus入门/', 'url': 'https://www.ddkk.com/category/orm/mybatisplus/5/index.html'})
    # study_data_url.append({'file_path': 'JAVA/ORM框架/MyBatis-Plus教程/', 'url': 'https://www.ddkk.com/category/orm/mybatisplus/1/index.html'})
    # study_data_url.append({'file_path': 'JAVA/ORM框架/JFinal教程/', 'url': 'https://www.ddkk.com/category/orm/jfinal/index.html'})
    # study_data_url.append({'file_path': 'JAVA/ORM框架/Hibernate教程/', 'url': 'https://www.ddkk.com/category/orm/hibernate/index.html'})
    # study_data_url.append({'file_path': 'JAVA/ORM框架/SpringDataJPA入门/', 'url': 'https://www.ddkk.com/category/orm/springdatajpa/1/index.html'})
    # study_data_url.append({'file_path': 'JAVA/ORM框架/SpringDataJPA实战（1）/', 'url': 'https://www.ddkk.com/category/orm/springdatajpa/5/index.html'})
    # study_data_url.append({'file_path': 'JAVA/ORM框架/SpringDataJPA实战（2）/', 'url': 'https://www.ddkk.com/zhuanlan/orm/springdatajpa/6/index.html'})

    # J2EE框架
    # study_data_url.append({'file_path': 'JAVA/J2EE框架/Spring教程/', 'url': 'https://www.ddkk.com/category/j2ee/spring/1/index.html'})
    # study_data_url.append({'file_path': 'JAVA/J2EE框架/Spring源码分析/', 'url': 'https://www.ddkk.com/category/j2ee/spring/7/index.html'})
    # study_data_url.append({'file_path': 'JAVA/J2EE框架/SpringMVC教程/', 'url': 'https://www.ddkk.com/category/j2ee/springmvc/1/index.html'})
    # study_data_url.append({'file_path': 'JAVA/J2EE框架/SpringMVC源码/', 'url': 'https://www.ddkk.com/category/j2ee/springmvc/7/index.html'})
    # study_data_url.append({'file_path': 'JAVA/J2EE框架/SpringBoot源码/', 'url': 'https://www.ddkk.com/category/j2ee/springboot/6/index.html'})
    # TODO 此处有一个图片异常访问
    # study_data_url.append({'file_path': 'JAVA/J2EE框架/SpringBoot实战/', 'url': 'https://www.ddkk.com/category/j2ee/springboot/8/index.html'})
    # study_data_url.append({'file_path': 'JAVA/J2EE框架/SpringBoot实战（1）/', 'url': 'https://www.ddkk.com/category/j2ee/springboot/4/index.html'})
    # study_data_url.append({'file_path': 'JAVA/J2EE框架/SpringBoot实战（2）/', 'url': 'https://www.ddkk.com/category/j2ee/springboot/5/index.html'})
    # study_data_url.append({'file_path': 'JAVA/J2EE框架/SpringCloud教程/', 'url': 'https://www.ddkk.com/category/j2ee/springcloud/1/index.html'})
    # TODO 该链接中存在请求链接地址错误问题
    # study_data_url.append({'file_path': 'JAVA/J2EE框架/SpringCloud Alibaba实战（1）/', 'url': 'https://www.ddkk.com/category/j2ee/springcloudalibaba/1/index.html'})
    # study_data_url.append({'file_path': 'JAVA/J2EE框架/SpringCloud Alibaba实战（2）/', 'url': 'https://www.ddkk.com/category/j2ee/springcloudalibaba/2/index.html'})
    # study_data_url.append({'file_path': 'JAVA/J2EE框架/SpringCloud Alibaba实战（3）/', 'url': 'https://www.ddkk.com/category/j2ee/springcloudalibaba/3/index.html'})
    # study_data_url.append({'file_path': 'JAVA/J2EE框架/SpringCloud 实战/', 'url': 'https://www.ddkk.com/category/j2ee/springcloud/2/index.html'})
    # study_data_url.append({'file_path': 'JAVA/J2EE框架/SpringBoot 3.x实战（1）/', 'url': 'https://www.ddkk.com/category/j2ee/springboot/7/index.html'})
    # study_data_url.append({'file_path': 'JAVA/J2EE框架/SpringBoot 3.x实战（2）/', 'url': 'https://www.ddkk.com/category/j2ee/springboot/9/index.html'})
    # study_data_url.append({'file_path': 'JAVA/J2EE框架/Nepxion 教程/', 'url': 'https://www.ddkk.com/category/j2ee/nepxion/1/index.html'})
    # study_data_url.append({'file_path': 'JAVA/J2EE框架/Dubbo 源码解析/', 'url': 'https://www.ddkk.com/category/j2ee/dubbo/1/index.html'})
    # study_data_url.append({'file_path': 'JAVA/J2EE框架/Dubbo2.7源码解析/', 'url': 'https://www.ddkk.com/category/j2ee/dubbo/3/index.html'})
    # study_data_url.append({'file_path': 'JAVA/J2EE框架/Dubbo 3.x源码解析/', 'url': 'https://www.ddkk.com/category/j2ee/dubbo/2/index.html'})
    # study_data_url.append({'file_path': 'JAVA/J2EE框架/Dubbo 实战/', 'url': 'https://www.ddkk.com/category/j2ee/dubbo/4/index.html'})

    # 安全框架
    # study_data_url.append({'file_path': 'JAVA/安全框架/Spring Security教程/', 'url': 'https://www.ddkk.com/category/security/springsecurity/1/index.html'})
    # study_data_url.append({'file_path': 'JAVA/安全框架/Spring Security入门/', 'url': 'https://www.ddkk.com/category/security/springsecurity/5/index.html'})
    # study_data_url.append({'file_path': 'JAVA/安全框架/Spring Security速成/', 'url': 'https://www.ddkk.com/category/security/springsecurity/6/index.html'})
    # study_data_url.append({'file_path': 'JAVA/安全框架/Spring Security源码解析/', 'url': 'https://www.ddkk.com/category/security/springsecurity/10/index.html'})
    # study_data_url.append({'file_path': 'JAVA/安全框架/Spring Security实战（1）/', 'url': 'https://www.ddkk.com/category/security/springsecurity/7/index.html'})
    # study_data_url.append({'file_path': 'JAVA/安全框架/Spring Security实战（2）/', 'url': 'https://www.ddkk.com/category/security/springsecurity/8/index.html'})
    # study_data_url.append({'file_path': 'JAVA/安全框架/Spring Security实战（3）/', 'url': 'https://www.ddkk.com/category/security/springsecurity/9/index.html'})
    # study_data_url.append({'file_path': 'JAVA/安全框架/Spring Security实战（4）/', 'url': 'https://www.ddkk.com/category/security/springsecurity/11/index.html'})
    # study_data_url.append({'file_path': 'JAVA/安全框架/Shiro 教程/', 'url': 'https://www.ddkk.com/category/security/shiro/1/index.html'})
    # study_data_url.append({'file_path': 'JAVA/安全框架/Shiro 入门/', 'url': 'https://www.ddkk.com/category/security/shiro/6/index.html'})
    # study_data_url.append({'file_path': 'JAVA/安全框架/SpringBoot + Shiro 速成/', 'url': 'https://www.ddkk.com/category/security/shiro/5/index.html'})
    # study_data_url.append({'file_path': 'JAVA/安全框架/Shiro 实战 (1)/', 'url': 'https://www.ddkk.com/category/security/shiro/7/index.html'})
    # study_data_url.append({'file_path': 'JAVA/安全框架/Shiro 实战 (2)/', 'url': 'https://www.ddkk.com/category/security/shiro/8/index.html'})
    # study_data_url.append({'file_path': 'JAVA/安全框架/OAuth 2.0 教程/', 'url': 'https://www.ddkk.com/category/security/oauth2/index.html'})
    # study_data_url.append({'file_path': 'JAVA/安全框架/OAuth 2.0 实战/', 'url': 'https://www.ddkk.com/category/security/oauth2/2/index.html'})
    # study_data_url.append({'file_path': 'JAVA/安全框架/JWT 教程/', 'url': 'https://www.ddkk.com/category/security/jwt/index.html'})
    # study_data_url.append({'file_path': 'JAVA/安全框架/Spring Authorization Server 教程/', 'url': 'https://www.ddkk.com/category/security/springauthorization/index.html'})

    # 消息队列
    # study_data_url.append({'file_path': 'JAVA/消息队列/ActiveMQ 实战（1）/', 'url': 'https://www.ddkk.com/category/mq/activemq/1/index.html'})
    # study_data_url.append({'file_path': 'JAVA/消息队列/ActiveMQ 实战（2）/', 'url': 'https://www.ddkk.com/category/mq/activemq/2/index.html'})
    # study_data_url.append({'file_path': 'JAVA/消息队列/ActiveMQ 实战（3）/', 'url': 'https://www.ddkk.com/category/mq/activemq/3/index.html'})
    # study_data_url.append({'file_path': 'JAVA/消息队列/ActiveMQ 实战（4）/', 'url': 'https://www.ddkk.com/category/mq/activemq/4/index.html'})
    # study_data_url.append({'file_path': 'JAVA/消息队列/RabbitMQ 实战（1）/', 'url': 'https://www.ddkk.com/category/mq/rabbitmq/1/index.html'})
    # study_data_url.append({'file_path': 'JAVA/消息队列/RabbitMQ 实战（2）/', 'url': 'https://www.ddkk.com/category/mq/rabbitmq/2/index.html'})
    # study_data_url.append({'file_path': 'JAVA/消息队列/RabbitMQ 实战（3）/', 'url': 'https://www.ddkk.com/category/mq/rabbitmq/3/index.html'})
    # study_data_url.append({'file_path': 'JAVA/消息队列/RabbitMQ 实战（4）/', 'url': 'https://www.ddkk.com/category/mq/rabbitmq/4/index.html'})
    # study_data_url.append({'file_path': 'JAVA/消息队列/Kafka 实战（1）/', 'url': 'https://www.ddkk.com/category/mq/kafka/1/index.html'})
    # study_data_url.append({'file_path': 'JAVA/消息队列/Kafka 实战（2）/', 'url': 'https://www.ddkk.com/category/mq/kafka/2/index.html'})
    # study_data_url.append({'file_path': 'JAVA/消息队列/Kafka 实战（3）/', 'url': 'https://www.ddkk.com/category/mq/kafka/3/index.html'})
    # study_data_url.append({'file_path': 'JAVA/消息队列/Kafka 实战（4）/', 'url': 'https://www.ddkk.com/category/mq/kafka/4/index.html'})
    # study_data_url.append({'file_path': 'JAVA/消息队列/Kafka 实战（5）/', 'url': 'https://www.ddkk.com/category/mq/kafka/5/index.html'})
    # study_data_url.append({'file_path': 'JAVA/消息队列/Kafka 实战（6）/', 'url': 'https://www.ddkk.com/category/mq/kafka/6/index.html'})
    # study_data_url.append({'file_path': 'JAVA/消息队列/Kafka 实战（7）/', 'url': 'https://www.ddkk.com/category/mq/kafka/7/index.html'})
    # study_data_url.append({'file_path': 'JAVA/消息队列/Kafka 源码解析/', 'url': 'https://www.ddkk.com/category/mq/kafka/8/index.html'})
    # study_data_url.append({'file_path': 'JAVA/消息队列/RocketMQ 源码解析（1）/', 'url': 'https://www.ddkk.com/category/mq/rocketmq/1/index.html'})
    # study_data_url.append({'file_path': 'JAVA/消息队列/RocketMQ 源码解析（2）/', 'url': 'https://www.ddkk.com/category/mq/rocketmq/2/index.html'})
    # study_data_url.append({'file_path': 'JAVA/消息队列/RocketMQ 源码解析（3）/', 'url': 'https://www.ddkk.com/category/mq/rocketmq/3/index.html'})
    # study_data_url.append({'file_path': 'JAVA/消息队列/RocketMQ 源码解析（4）/', 'url': 'https://www.ddkk.com/category/mq/rocketmq/4/index.html'})
    # study_data_url.append({'file_path': 'JAVA/消息队列/RocketMQ 实战（1）/', 'url': 'https://www.ddkk.com/category/mq/rocketmq/5/index.html'})
    # study_data_url.append({'file_path': 'JAVA/消息队列/RocketMQ 实战（2）/', 'url': 'https://www.ddkk.com/category/mq/rocketmq/6/index.html'})
    # study_data_url.append({'file_path': 'JAVA/消息队列/RocketMQ 实战（3）/', 'url': 'https://www.ddkk.com/category/mq/rocketmq/7/index.html'})
    # study_data_url.append({'file_path': 'JAVA/消息队列/RocketMQ 实战（4）/', 'url': 'https://www.ddkk.com/category/mq/rocketmq/8/index.html'})

    # 搜索引擎
    # study_data_url.append({'file_path': 'JAVA/搜索引擎/ElasticSearch 实战（1）/', 'url': 'https://www.ddkk.com/category/search/elasticsearch/1/index.html'})
    # study_data_url.append({'file_path': 'JAVA/搜索引擎/ElasticSearch 实战（2）/', 'url': 'https://www.ddkk.com/category/search/elasticsearch/2/index.html'})
    # study_data_url.append({'file_path': 'JAVA/搜索引擎/ElasticSearch 实战（3）/', 'url': 'https://www.ddkk.com/category/search/elasticsearch/3/index.html'})
    # study_data_url.append({'file_path': 'JAVA/搜索引擎/ElasticSearch 实战（4）/', 'url': 'https://www.ddkk.com/category/search/elasticsearch/4/index.html'})
    # study_data_url.append({'file_path': 'JAVA/搜索引擎/ElasticSearch 实战（5）/', 'url': 'https://www.ddkk.com/category/search/elasticsearch/5/index.html'})
    # study_data_url.append({'file_path': 'JAVA/搜索引擎/ElasticSearch 实战（6）/', 'url': 'https://www.ddkk.com/category/search/elasticsearch/6/index.html'})
    # study_data_url.append({'file_path': 'JAVA/搜索引擎/ElasticSearch 实战（7）/', 'url': 'https://www.ddkk.com/category/search/elasticsearch/7/index.html'})
    # study_data_url.append({'file_path': 'JAVA/搜索引擎/ElasticSearch 实战（8）/', 'url': 'https://www.ddkk.com/category/search/elasticsearch/8/index.html'})
    # study_data_url.append({'file_path': 'JAVA/搜索引擎/Solr实战/', 'url': 'https://www.ddkk.com/category/search/solr/2/index.html'})
    # study_data_url.append({'file_path': 'JAVA/搜索引擎/Solr速成/', 'url': 'https://www.ddkk.com/category/search/solr/3/index.html'})
    # study_data_url.append({'file_path': 'JAVA/搜索引擎/Solr源码解析/', 'url': 'https://www.ddkk.com/category/search/solr/1/index.html'})
    # study_data_url.append({'file_path': 'JAVA/搜索引擎/SolrCloud教程/', 'url': 'https://www.ddkk.com/category/search/solrcloud/index.html'})

    # 分布式事务
    # study_data_url.append({'file_path': 'JAVA/分布式事务/分布式事务 实战（1）/', 'url': 'https://www.ddkk.com/category/transaction/1/index.html'})
    # study_data_url.append({'file_path': 'JAVA/分布式事务/分布式事务 实战（2）/', 'url': 'https://www.ddkk.com/category/transaction/2/index.html'})
    # study_data_url.append({'file_path': 'JAVA/分布式事务/分布式事务 实战（3）/', 'url': 'https://www.ddkk.com/category/transaction/3/index.html'})
    # study_data_url.append({'file_path': 'JAVA/分布式事务/分布式事务 实战（4）/', 'url': 'https://www.ddkk.com/category/transaction/4/index.html'})
    # study_data_url.append({'file_path': 'JAVA/分布式事务/分布式事务 实战（5）/', 'url': 'https://www.ddkk.com/category/transaction/6/index.html'})
    # study_data_url.append({'file_path': 'JAVA/分布式事务/分布式事务 实战（6）/', 'url': 'https://www.ddkk.com/category/transaction/7/index.html'})
    # study_data_url.append({'file_path': 'JAVA/分布式事务/分布式事务 Seata 教程/', 'url': 'https://www.ddkk.com/category/transaction/5/index.html'})

    # 分布式存储
    # study_data_url.append({'file_path': 'JAVA/分布式存储/Minio 教程/', 'url': 'https://www.ddkk.com/category/filestorage/minio/1/index.html'})
    # study_data_url.append({'file_path': 'JAVA/分布式存储/FastDFS 入门/', 'url': 'https://www.ddkk.com/category/filestorage/fastdfs/1/index.html'})
    # study_data_url.append({'file_path': 'JAVA/分布式存储/FastDFS 基础/', 'url': 'https://www.ddkk.com/category/filestorage/fastdfs/2/index.html'})
    # study_data_url.append({'file_path': 'JAVA/分布式存储/HDFS 教程/', 'url': 'https://www.ddkk.com/category/filestorage/hdfs/1/index.html'})

    # 服务器框架
    # study_data_url.append({'file_path': 'JAVA/服务器框架/Netty 入门（1）/', 'url': 'https://www.ddkk.com/category/server/netty/5/index.html'})
    # study_data_url.append({'file_path': 'JAVA/服务器框架/Netty 入门（2）/', 'url': 'https://www.ddkk.com/category/server/netty/2/index.html'})
    # study_data_url.append({'file_path': 'JAVA/服务器框架/Netty 基础/', 'url': 'https://www.ddkk.com/category/server/netty/4/index.html'})
    # study_data_url.append({'file_path': 'JAVA/服务器框架/Netty 源码解析（1）/', 'url': 'https://www.ddkk.com/category/server/netty/1/index.html'})
    # study_data_url.append({'file_path': 'JAVA/服务器框架/Netty 源码解析（2）/', 'url': 'https://www.ddkk.com/category/server/netty/3/index.html'})
    # study_data_url.append({'file_path': 'JAVA/服务器框架/Tomcat 内核详解/', 'url': 'https://www.ddkk.com/category/server/tomcat/3/index.html'})
    # study_data_url.append({'file_path': 'JAVA/服务器框架/Tomcat 源码（A）/', 'url': 'https://www.ddkk.com/category/server/tomcat/1/index.html'})
    # study_data_url.append({'file_path': 'JAVA/服务器框架/Tomcat 源码（B）/', 'url': 'https://www.ddkk.com/category/server/tomcat/2/index.html'})
    # study_data_url.append({'file_path': 'JAVA/服务器框架/Linux 基础/', 'url': 'https://www.ddkk.com/category/server/linux/4/index.html'})
    # study_data_url.append({'file_path': 'JAVA/服务器框架/Linux 教程/', 'url': 'https://www.ddkk.com/category/server/linux/1/index.html'})
    # study_data_url.append({'file_path': 'JAVA/服务器框架/Linux 实战（1）/', 'url': 'https://www.ddkk.com/category/server/linux/2/index.html'})
    # study_data_url.append({'file_path': 'JAVA/服务器框架/Linux 实战（2）/', 'url': 'https://www.ddkk.com/category/server/linux/5/index.html'})
    # study_data_url.append({'file_path': 'JAVA/服务器框架/Linux 系统编程/', 'url': 'https://www.ddkk.com/category/server/linux/3/index.html'})

    # 大数据框架
    # study_data_url.append({'file_path': 'JAVA/大数据框架/Flink 深入/', 'url': 'https://www.ddkk.com/category/bigdata/flink/4/index.html'})
    # study_data_url.append({'file_path': 'JAVA/大数据框架/Flink 入门/', 'url': 'https://www.ddkk.com/category/bigdata/flink/1/index.html'})
    # study_data_url.append({'file_path': 'JAVA/大数据框架/FlinkSQL 入门/', 'url': 'https://www.ddkk.com/category/bigdata/flink/4/index.html'})
    # study_data_url.append({'file_path': 'JAVA/大数据框架/Flink 速成/', 'url': 'https://www.ddkk.com/category/bigdata/flink/2/index.html'})
    # study_data_url.append({'file_path': 'JAVA/大数据框架/Flink 笔记/', 'url': 'https://www.ddkk.com/category/bigdata/flink/5/index.html'})
    # study_data_url.append({'file_path': 'JAVA/大数据框架/Flink 教程/', 'url': 'https://www.ddkk.com/category/bigdata/hive/2/index.html'})
    # study_data_url.append({'file_path': 'JAVA/大数据框架/Hive 实战/', 'url': 'https://www.ddkk.com/category/bigdata/hive/1/index.html'})
    # study_data_url.append({'file_path': 'JAVA/大数据框架/Hadoop 入门/', 'url': 'https://www.ddkk.com/category/bigdata/hadoop/1/index.html'})
    # study_data_url.append({'file_path': 'JAVA/大数据框架/Hadoop 教程/', 'url': 'https://www.ddkk.com/category/bigdata/hadoop/2/index.html'})
    # study_data_url.append({'file_path': 'JAVA/大数据框架/Hadoop 实战/', 'url': 'https://www.ddkk.com/category/bigdata/hadoop/3/index.html'})
    # study_data_url.append({'file_path': 'JAVA/大数据框架/HBase 教程/', 'url': 'https://www.ddkk.com/category/bigdata/hbase/index.html'})
    # study_data_url.append({'file_path': 'JAVA/大数据框架/Storm 教程/', 'url': 'https://www.ddkk.com/category/bigdata/storm/index.html'})
    # study_data_url.append({'file_path': 'JAVA/大数据框架/Spark 教程/', 'url': 'https://www.ddkk.com/category/bigdata/spark/2/index.html'})
    # study_data_url.append({'file_path': 'JAVA/大数据框架/Spark 深入解析/', 'url': 'https://www.ddkk.com/category/bigdata/spark/1/index.html'})

    # 作业调度
    # study_data_url.append({'file_path': 'JAVA/作业调度/XXL-JOB 教程/', 'url': 'https://www.ddkk.com/category/job/xxljob/1/index.html'})
    # study_data_url.append({'file_path': 'JAVA/作业调度/ElasticJob Cloud 教程/', 'url': 'https://www.ddkk.com/category/job/elasticJobcloud/index.html'})
    # study_data_url.append({'file_path': 'JAVA/作业调度/Elastic Job Lite 教程/', 'url': 'https://www.ddkk.com/category/job/elasticjoblite/index.html'})
    # study_data_url.append({'file_path': 'JAVA/作业调度/Quartz 教程/', 'url': 'https://www.ddkk.com/category/job/quartz/1/index.html'})
    # study_data_url.append({'file_path': 'JAVA/作业调度/JOB 源码解析/', 'url': 'https://www.ddkk.com/category/job/xxljob/2/index.html'})
    # study_data_url.append({'file_path': 'JAVA/作业调度/Java 任务调度/', 'url': 'https://www.ddkk.com/category/job/job/1/index.html'})
    # study_data_url.append({'file_path': 'JAVA/作业调度/Quartz 实战(1)/', 'url': 'https://www.ddkk.com/category/job/quartz/3/index.html'})
    # study_data_url.append({'file_path': 'JAVA/作业调度/Quartz 实战(2)/', 'url': 'https://www.ddkk.com/category/job/quartz/4/index.html'})

    # 注册中心
    # study_data_url.append({'file_path': 'JAVA/注册中心/Eureka 教程/', 'url':'https://www.ddkk.com/category/registered/eureka/index.html'})
    # study_data_url.append({'file_path': 'JAVA/注册中心/Eureka 源码解析/', 'url':'https://www.ddkk.com/category/registered/eureka/1/index.html'})
    # study_data_url.append({'file_path': 'JAVA/注册中心/Nacos 教程/', 'url':'https://www.ddkk.com/category/registered/nacos/index.html'})
    # study_data_url.append({'file_path': 'JAVA/注册中心/Nacos 实战/', 'url':'https://www.ddkk.com/category/registered/nacos/1/index.html'})
    # study_data_url.append({'file_path': 'JAVA/注册中心/Consul 教程/', 'url':'https://www.ddkk.com/category/registered/consul/index.html'})
    # study_data_url.append({'file_path': 'JAVA/注册中心/ZooKeeper 教程/', 'url':'https://www.ddkk.com/category/registered/zookeeper/index.html'})
    # study_data_url.append({'file_path': 'JAVA/注册中心/ZooKeeper 源码解析(1)/', 'url':'https://www.ddkk.com/category/registered/zookeeper/1/index.html'})
    # study_data_url.append({'file_path': 'JAVA/注册中心/ZooKeeper 源码解析(2)/', 'url':'https://www.ddkk.com/category/registered/zookeeper/2/index.html'})

    # 配置中心
    # study_data_url.append({'file_path': 'JAVA/配置中心/Apollo 教程/', 'url': 'https://www.ddkk.com/category/config/apollo/index.html'})
    # study_data_url.append({'file_path': 'JAVA/配置中心/Apollo 教程/', 'url': 'https://www.ddkk.com/category/registered/nacos/index.html'})
    # study_data_url.append({'file_path': 'JAVA/配置中心/SpringCloud Config 教程/', 'url': 'https://www.ddkk.com/category/config/springcloudconfig/index.html'})
    # study_data_url.append({'file_path': 'JAVA/配置中心/Disconf 教程/', 'url': 'https://www.ddkk.com/category/config/disconf/index.html'})

    # 链路追踪
    # study_data_url.append({'file_path': 'JAVA/链路追踪/SkyWalking 教程/', 'url': 'https://www.ddkk.com/category/linktrack/skywalking/index.html'})
    # study_data_url.append({'file_path': 'JAVA/链路追踪/Zipkin 教程/', 'url': 'https://www.ddkk.com/category/linktrack/zipkin/index.html'})
    # study_data_url.append({'file_path': 'JAVA/链路追踪/CAT 教程/', 'url': 'https://www.ddkk.com/category/linktrack/cat/index.html'})
    # study_data_url.append({'file_path': 'JAVA/链路追踪/PinPoint 教程/', 'url': 'https://www.ddkk.com/category/linktrack/pinpoint/index.html'})

    # 服务保障
    # study_data_url.append({'file_path': 'JAVA/服务保障/Hystrix 教程/', 'url': 'https://www.ddkk.com/category/guarantee/hystrix/index.html'})
    # study_data_url.append({'file_path': 'JAVA/服务保障/Sentinel 教程/', 'url': 'https://www.ddkk.com/category/guarantee/sentinel/index.html'})
    # study_data_url.append({'file_path': 'JAVA/服务保障/Sentinel 源码解析/', 'url': 'https://www.ddkk.com/category/guarantee/sentinelym/index.html'})
    # study_data_url.append({'file_path': 'JAVA/服务保障/Resilience4j 源码解析/', 'url': 'https://www.ddkk.com/category/guarantee/resilience4j/index.html'})

    # 监控工具
    # study_data_url.append({'file_path': 'JAVA/监控工具/Prometheus 教程/', 'url': 'https://www.ddkk.com/category/monitoring/prometheus/index.html'})
    # study_data_url.append({'file_path': 'JAVA/监控工具/kibana 可视化/', 'url': 'https://www.ddkk.com/category/monitoring/kibana/index.html'})
    # study_data_url.append({'file_path': 'JAVA/监控工具/Spring Boot Admin 实战/', 'url': 'https://www.ddkk.com/category/monitoring/springbootadmin/index.html'})

    # Java 设计模式
    # study_data_url.append({'file_path': 'JAVA/Java 设计模式/', 'url': 'https://www.ddkk.com/category/design/java/index.html'})

    # Java 其他
    # study_data_url.append({'file_path': 'JAVA/Java 其他/Java 秒懂小文/', 'url': 'https://www.ddkk.com/category/java/javatm/index.html'})
    # study_data_url.append({'file_path': 'JAVA/Java 其他/Tomcat 内核详解/', 'url': 'https://www.ddkk.com/category/server/tomcat/3/index.html'})
    # study_data_url.append({'file_path': 'JAVA/Java 其他/JSP 教程/', 'url': 'https://www.ddkk.com/category/java/jsp/index.html'})
    # study_data_url.append({'file_path': 'JAVA/Java 其他/Swing 教程/', 'url': 'https://www.ddkk.com/category/java/swing/index.html'})
    # study_data_url.append({'file_path': 'JAVA/Java 其他/Scala 教程/', 'url': 'https://www.ddkk.com/category/java/scala/index.html'})
    # study_data_url.append({'file_path': 'JAVA/Java 其他/Groovy 教程/', 'url': 'https://www.ddkk.com/category/java/groovy/index.html'})
    # study_data_url.append({'file_path': 'JAVA/Java 其他/Scala 教程/', 'url': 'https://www.ddkk.com/category/java/scala/index.html'})
    # study_data_url.append({'file_path': 'JAVA/Java 其他/Kotlin 教程/', 'url': 'https://www.ddkk.com/category/java/kotlin/index.html'})
    # study_data_url.append({'file_path': 'JAVA/Java 其他/Drools 教程/', 'url': 'https://www.ddkk.com/category/other/drools/1/index.html'})

    # Redis 教程
    # study_data_url.append({'file_path': '数据库/Redis/Redis基础/', 'url': 'https://www.ddkk.com/category/db/redis/index.html'})
    # study_data_url.append({'file_path': '数据库/Redis/Redis实战/', 'url': 'https://www.ddkk.com/category/db/redis-action/index.html'})
    # study_data_url.append({'file_path': '数据库/Redis/Redis源码解析（3）/', 'url': 'https://www.ddkk.com/category/db/redis/1/index.html'})
    # study_data_url.append({'file_path': '数据库/Redis/Redis源码解析（4）/', 'url': 'https://www.ddkk.com/category/db/redis/4/index.html'})
    # study_data_url.append({'file_path': '数据库/Redis/Redis源码解析（5）/', 'url': 'https://www.ddkk.com/category/db/redis/5/index.html'})
    # study_data_url.append({'file_path': '数据库/Redis/Redis源码解析（6）/', 'url': 'https://www.ddkk.com/category/db/redis/6/index.html'})
    # study_data_url.append({'file_path': '数据库/Redis/Redis源码解析（7）/', 'url': 'https://www.ddkk.com/category/db/redis/7/index.html'})
    # study_data_url.append({'file_path': '数据库/Redis/Redis源码解析（8）/', 'url': 'https://www.ddkk.com/category/db/redis/8/index.html'})

    # Oracle 教程
    # study_data_url.append({'file_path': '数据库/Oracle/Oracle教程/', 'url': 'https://www.ddkk.com/category/db/oracle/1/index.html'})
    # study_data_url.append({'file_path': '数据库/Oracle/Oracle基础/', 'url': 'https://www.ddkk.com/category/db/oracle/3/index.html'})
    # study_data_url.append({'file_path': '数据库/Oracle/Oracle入门教程/', 'url': 'https://www.ddkk.com/category/db/oracle/2/index.html'})
    # study_data_url.append({'file_path': '数据库/Oracle/Oracle PL（SQL基础）/', 'url': 'https://www.ddkk.com/category/db/oracle/4/index.html'})

    # SQL 教程
    # study_data_url.append({'file_path': '数据库/MySQL/MySQL教程/', 'url': 'https://www.ddkk.com/category/db/mysql/index.html'})
    # study_data_url.append({'file_path': '数据库/MySQL/MySQL拾遗/', 'url': 'https://www.ddkk.com/category/db/mysqlsy/index.html'})
    # study_data_url.append({'file_path': '数据库/MySQL/MySQL提升/', 'url': 'https://www.ddkk.com/category/db/mysql/1/index.html'})
    # study_data_url.append({'file_path': '数据库/MySQL/MySQL实战/', 'url': 'https://www.ddkk.com/category/db/mysql/2/index.html'})
    # study_data_url.append({'file_path': '数据库/MySQL/MySQL调优/', 'url': 'https://www.ddkk.com/category/db/mysql/3/index.html'})
    # study_data_url.append({'file_path': '数据库/MySQL/MySQL基础进阶（1）/', 'url': 'https://www.ddkk.com/category/db/mysql/5/index.html'})
    # study_data_url.append({'file_path': '数据库/MySQL/MySQL基础进阶（2）/', 'url': 'https://www.ddkk.com/category/db/mysql/7/index.html'})
    # study_data_url.append({'file_path': '数据库/MySQL/MySQL基础进阶（3）/', 'url': 'https://www.ddkk.com/category/db/mysql/8/index.html'})
    # study_data_url.append({'file_path': '数据库/MySQL/MySQL高级进阶/', 'url': 'https://www.ddkk.com/category/db/mysql/6/index.html'})

    # SQL 优化/组件
    # study_data_url.append({'file_path': '数据库/SQL/SQL基础/', 'url': 'https://www.ddkk.com/category/db/sql/index.html'})
    # study_data_url.append({'file_path': '数据库/SQL/SQL教程/', 'url': 'https://www.ddkk.com/category/db/sqlweici/index.html'})
    # study_data_url.append({'file_path': '数据库/SQL/SQLite教程/', 'url': 'https://www.ddkk.com/category/db/sqlite/index.html'})

    # SQL 分库分表
    # study_data_url.append({'file_path': '数据库/分库分表/MyCat实战（1）/', 'url': 'https://www.ddkk.com/category/sharding/mycat/1/index.html'})
    # study_data_url.append({'file_path': '数据库/分库分表/MyCat实战（2）/', 'url': 'https://www.ddkk.com/category/sharding/mycat/2/index.html'})
    # study_data_url.append({'file_path': '数据库/分库分表/MyCat实战（3）/', 'url': 'https://www.ddkk.com/category/sharding/mycat/3/index.html'})
    # study_data_url.append({'file_path': '数据库/分库分表/MyCat实战（4）/', 'url': 'https://www.ddkk.com/category/sharding/mycat/4/index.html'})
    # study_data_url.append({'file_path': '数据库/分库分表/Sharding-JDBC 实战（1）/', 'url': 'https://www.ddkk.com/category/sharding/shardingjdbc/1/index.html'})
    # study_data_url.append({'file_path': '数据库/分库分表/Sharding-JDBC 实战（2）/', 'url': 'https://www.ddkk.com/category/sharding/shardingjdbc/2/index.html'})
    # study_data_url.append({'file_path': '数据库/分库分表/Sharding-JDBC 实战（3）/', 'url': 'https://www.ddkk.com/category/sharding/shardingjdbc/3/index.html'})
    # study_data_url.append({'file_path': '数据库/分库分表/Sharding-JDBC 实战（4）/', 'url': 'https://www.ddkk.com/category/sharding/shardingjdbc/4/index.html'})
    # study_data_url.append({'file_path': '数据库/分库分表/Sharding-Sphere 实战（1）/', 'url': 'https://www.ddkk.com/category/sharding/shardingsphere/1/index.html'})
    # study_data_url.append({'file_path': '数据库/分库分表/Sharding-Sphere 实战（2）/', 'url': 'https://www.ddkk.com/category/sharding/shardingsphere/2/index.html'})
    # study_data_url.append({'file_path': '数据库/分库分表/Sharding-Sphere 实战（3）/', 'url': 'https://www.ddkk.com/category/sharding/shardingsphere/3/index.html'})
    # study_data_url.append({'file_path': '数据库/分库分表/Sharding-Sphere 实战（4）/', 'url': 'https://www.ddkk.com/category/sharding/shardingsphere/4/index.html'})


    # 容器服务
    # study_data_url.append({'file_path': '容器服务/Kubernetes/Kubernetes-实战（1）/', 'url': 'https://www.ddkk.com/category/container/kubernetes/1/index.html'})
    # study_data_url.append({'file_path': '容器服务/Kubernetes/Kubernetes-实战（2）/', 'url': 'https://www.ddkk.com/category/container/kubernetes/2/index.html'})
    # study_data_url.append({'file_path': '容器服务/Kubernetes/Kubernetes-实战（3）/', 'url': 'https://www.ddkk.com/category/container/kubernetes/3/index.html'})
    # study_data_url.append({'file_path': '容器服务/Kubernetes/Kubernetes-实战（4）/', 'url': 'https://www.ddkk.com/category/container/kubernetes/4/index.html'})
    # study_data_url.append({'file_path': '容器服务/Kubernetes/Kubernetes-实战（5）/', 'url': 'https://www.ddkk.com/category/container/kubernetes/5/index.html'})
    # study_data_url.append({'file_path': '容器服务/Kubernetes/Kubernetes-实战（6）/', 'url': 'https://www.ddkk.com/category/container/kubernetes/6/index.html'})
    # study_data_url.append({'file_path': '容器服务/Kubernetes/Kubernetes-实战（7）/', 'url': 'https://www.ddkk.com/category/container/kubernetes/7/index.html'})
    # study_data_url.append({'file_path': '容器服务/Kubernetes/Kubernetes-实战（8）/', 'url': 'https://www.ddkk.com/category/container/kubernetes/8/index.html'})
    # study_data_url.append({'file_path': '容器服务/Kubernetes/Kubernetes-实战（9）/', 'url': 'https://www.ddkk.com/category/container/kubernetes/9/index.html'})
    # study_data_url.append({'file_path': '容器服务/Kubernetes/Kubernetes-实战（10）/', 'url': 'https://www.ddkk.com/category/container/kubernetes/10/index.html'})
    # study_data_url.append({'file_path': '容器服务/Kubernetes/Kubernetes-实战（11）/', 'url': 'https://www.ddkk.com/category/container/kubernetes/11/index.html'})
    # study_data_url.append({'file_path': '容器服务/Kubernetes/Kubernetes-实战（12）/', 'url': 'https://www.ddkk.com/category/container/kubernetes/12/index.html'})
    # study_data_url.append({'file_path': '容器服务/Docker/Docker实战（1）/', 'url': 'https://www.ddkk.com/category/container/docker/1/index.html'})
    # study_data_url.append({'file_path':                              '容器服务/Docker/Docker实战（2）/', 'url': 'https://www.ddkk.com/category/container/docker/2/index.html'})
    # study_data_url.append({'file_path': '容器服务/Docker/Docker实战（3）/', 'url': 'https://www.ddkk.com/category/container/docker/3/index.html'})
    # study_data_url.append({'file_path': '容器服务/Docker/Docker实战（4）/', 'url': 'https://www.ddkk.com/category/container/docker/4/index.html'})

    # 数据结构
    # study_data_url.append({'file_path': '数据结构/数据结构与算法-基础（1）/', 'url': 'https://www.ddkk.com/category/algorithm/3/index.html'})
    # study_data_url.append({'file_path': '数据结构/数据结构与算法-基础（2）/', 'url': 'https://www.ddkk.com/category/algorithm/1/index.html'})
    # study_data_url.append({'file_path': '数据结构/数据结构与算法-基础（3）/', 'url': 'https://www.ddkk.com/category/algorithm/4/index.html'})
    # study_data_url.append({'file_path': '数据结构/数据结构与算法-基础（4）/', 'url': 'https://www.ddkk.com/category/algorithm/5/index.html'})
    # study_data_url.append({'file_path': '数据结构/数据结构与算法-实战（1）/', 'url': 'https://www.ddkk.com/category/algorithm/2/index.html'})
    # study_data_url.append({'file_path': '数据结构/数据结构与算法-实战（2）/', 'url': 'https://www.ddkk.com/category/algorithm/6/index.html'})
    # study_data_url.append({'file_path': '数据结构/数据结构与算法-实战（3）/', 'url': 'https://www.ddkk.com/category/algorithm/7/index.html'})
    # study_data_url.append({'file_path': '数据结构/数据结构与算法-实战（4）/', 'url': 'https://www.ddkk.com/category/algorithm/8/index.html'})
    # study_data_url.append({'file_path': '数据结构/数据结构与算法-实战（5）/', 'url': 'https://www.ddkk.com/category/algorithm/9/index.html'})
    # study_data_url.append({'file_path': '数据结构/数据结构与算法-实战（6）/', 'url': 'https://www.ddkk.com/category/algorithm/10/index.html'})
    # study_data_url.append({'file_path': '数据结构/数据结构与算法-实战（7）/', 'url': 'https://www.ddkk.com/category/algorithm/11/index.html'})
    # study_data_url.append({'file_path': '数据结构/数据结构与算法-实战（8）/', 'url': 'https://www.ddkk.com/category/algorithm/12/index.html'})

    # API 网关
    # study_data_url.append({'file_path': 'API网关/Gateway/SpringCloud Gateway（1）/', 'url': 'https://www.ddkk.com/category/gateway/springcloudgateway/1/index.html'})
    # study_data_url.append({'file_path': 'API网关/Gateway/SpringCloud Gateway（2）/', 'url': 'https://www.ddkk.com/category/gateway/springcloudgateway/2/index.html'})
    # study_data_url.append({'file_path': 'API网关/Zuul/SpringCloud Zuul教程/', 'url': 'https://www.ddkk.com/category/gateway/springcloudzuul/index.html'})
    # study_data_url.append({'file_path': 'API网关/Kong/Kong教程/', 'url': 'https://www.ddkk.com/category/gateway/kong/index.html'})
    # study_data_url.append({'file_path': 'API网关/Nginx/Nginx基础/', 'url': 'https://www.ddkk.com/category/server/nginx/1/index.html'})
    # study_data_url.append({'file_path': 'API网关/Nginx/Nginx精通/', 'url': 'https://www.ddkk.com/category/server/nginx/4/index.html'})
    # study_data_url.append({'file_path': 'API网关/Nginx/Nginx实战（1）/', 'url': 'https://www.ddkk.com/category/server/nginx/2/index.html'})
    # study_data_url.append({'file_path': 'API网关/Nginx/Nginx实战（2）/', 'url': 'https://www.ddkk.com/category/server/nginx/3/index.html'})

    # LeetCode算法题
    # study_data_url.append({'file_path': '脑洞(算法)/LeetCode/', 'url': 'https://www.ddkk.com/zhuanlan/leetcode/index.html'})

    # Python 教程
    # study_data_url.append({'file_path': 'Python/Python教程/', 'url': 'https://www.ddkk.com/category/other/python/1/index.html'})
    # study_data_url.append({'file_path': 'Python/Python进阶，爬虫/', 'url': 'https://www.ddkk.com/category/other/python/2/index.html'})
    # study_data_url.append({'file_path': 'Python/Python入门实战/', 'url': 'https://www.ddkk.com/category/other/python/4/index.html'})
    # study_data_url.append({'file_path': 'Python/Python进阶探索/', 'url': 'https://www.ddkk.com/category/other/python/3/index.html'})
    # study_data_url.append({'file_path': 'Python/Python快速上手/', 'url': 'https://www.ddkk.com/category/other/python/5/index.html'})
    # study_data_url.append({'file_path': 'Python/Python基础入门/', 'url': 'https://www.ddkk.com/category/other/python/6/index.html'})

    # Python 设计模式 教程
    # study_data_url.append({"file_path": "Python/Python设计模式-教程/", "url": "https://www.ddkk.com/category/design/python/index.html"})

    # 前端教程
    # study_data_url.append({'file_path': '前端/Node.js教程/', 'url': 'https://www.ddkk.com/category/qianduan/nodejs/index.html'})
    # study_data_url.append({'file_path': '前端/VUE教程/', 'url': 'https://www.ddkk.com/category/qianduan/vuejs/index.html'})
    # study_data_url.append({'file_path': '前端/React教程/', 'url': 'https://www.ddkk.com/category/qianduan/react/index.html'})
    # study_data_url.append({'file_path': '前端/TypeScript教程/', 'url': 'https://www.ddkk.com/category/qianduan/typescript/1/index.html'})
    # study_data_url.append({'file_path': '前端/Bootstrap教程/', 'url': 'https://www.ddkk.com/category/qianduan/bootstrap/1/index.html'})
    # study_data_url.append({'file_path': '前端/Angular教程/', 'url': 'https://www.ddkk.com/category/qianduan/angular/1/index.html'})

    # 其他语言/ JSON 教程
    # study_data_url.append({'file_path': '其他语言/JSON教程/', 'url': 'https://www.ddkk.com/category/other/json/index.html'})

    # 其他语言/ SVG 语法教程
    # study_data_url.append({'file_path': '其他语言/SVG教程/', 'url': 'https://www.ddkk.com/category/other/svg/index.html'})

    # 其他语言/网络协议
    # study_data_url.append({'file_path': '其他语言/网络协议/', 'url': 'https://www.ddkk.com/category/other/http/index.html'})

    # 爬取
    for item in study_data_url:
        # 文件路径
        folder = item['file_path']
        url = item['url']
        # 提取域名
        parse_url = urlparse(url)
        # scheme 获取协议部分、netloc (获取网络位置部分)
        main_url = parse_url.scheme + '://' + parse_url.netloc
        pull_away_html_note(url)

    # 处理类型为 category 类型的数据
    # note_info_category('https://www.ddkk.com/zhuanlan/newtiku/java.html', f'./javaTest.md')
    # download_file('https://www.ddkk.com/images/2023/10/25/1610/1698221436241.png', f'{folder}图片/')

    # 处理类型为 zhuanlan 类型的数据
    # note_info_zhuanlan('https://www.ddkk.com/zhuanlan/leetcode/01-99.html',  f'脑洞(算法)/LeetCode/1、LeetCode 刷题目录/1、LeetCode 之 001-099 刷题笔记')
